home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / quicktime / quicktime vr / vrscript / feature files / vr3dtexture.c < prev    next >
Encoding:
Text File  |  2000-06-23  |  9.2 KB  |  324 lines

  1. //////////
  2. //
  3. //    File:        VR3DTexture.c
  4. //
  5. //    Contains:    Support for adding a QuickTime movie or a picture as a texture on a QD3D object.
  6. //
  7. //    Written by:    Tim Monroe
  8. //                Parts modeled on BoxMoov code by Rick Evans and Robert Dierkes.
  9. //
  10. //    Copyright:    © 1996-1998 by Apple Computer, Inc., all rights reserved.
  11. //
  12. //    Change History (most recent first):
  13. //
  14. //       <8>         04/21/98    rtm        changed all occurrences of gw->portPixMap to GetGWorldPixMap(gw),
  15. //                                    to prevent crashes reported on Windows
  16. //       <7>         03/09/98    rtm        changed PICT-specific code to use the graphics importer routines;
  17. //                                    now we can open any image file format supported by QuickTime;
  18. //                                    incorporated code previously in the file VR3DObjects.c, in the routines
  19. //                                    VR3DObjects_LoadEmbeddedMovie and VR3DObjects_LoopEmbeddedMovie
  20. //       <6>         01/28/98    rtm        changed NewGWorld calls to QTNewGWorld
  21. //       <5>         01/27/98    rtm        made minor changes to VR3DTexture_Delete
  22. //       <4>         05/02/97    rtm        added fMediaHandler field to textures, for movies with sound
  23. //       <3>         01/14/97    rtm        added support for PICT textures
  24. //       <2>         12/17/96    rtm        modified VR3DTexture_AddToGroup to replace a texture shader
  25. //       <1>         12/16/96    rtm        first file; revised to personal coding style
  26. //       
  27. //////////
  28.  
  29. // header files
  30. #include <QuickDraw.h>
  31. #include <Resources.h>
  32.  
  33. #include <QD3D.h>
  34. #include <QD3DGroup.h>
  35. #include <QD3DShader.h>
  36. #include <QD3DSet.h>
  37.  
  38. #include "VR3DTexture.h"
  39. #include "VR3DObjects.h"
  40. #include "QTUtilities.h"
  41. #include "QTVRUtilities.h"
  42.  
  43.  
  44. //////////
  45. //
  46. // VR3DTexture_New
  47. // Create a new texture from a QuickTime movie or PICT file.
  48. //
  49. //////////
  50.  
  51. TextureHdl VR3DTexture_New (char *thePathName, Boolean isTextureMovie)
  52. {
  53.     FSSpec                        myFSSpec;
  54.     unsigned long                myPictMapAddr;
  55.     unsigned long                 myPictRowBytes;
  56.     GWorldPtr                     myGWorld;
  57.     PixMapHandle                 myPixMap;
  58.     GDHandle                    myOldGD;
  59.     GWorldPtr                    myOldGW;
  60.     Rect                        myBounds;
  61.     TQ3StoragePixmap            *myStrgPMapPtr;
  62.     TextureHdl                    myTexture = NULL;
  63.     GraphicsImportComponent        myImporter = NULL;
  64.     short                        myMovieFileRef;
  65.     QDErr                        myErr = noErr;
  66.  
  67.     myTexture = (TextureHdl)NewHandleClear(sizeof(Texture));
  68.     if (myTexture == NULL)
  69.         return(myTexture);
  70.         
  71.     HLock((Handle)myTexture);
  72.  
  73.     // save the current port
  74.     GetGWorld(&myOldGW, &myOldGD);
  75.         
  76.     FileUtils_MakeFSSpecForPathName(0, 0L, thePathName, &myFSSpec);
  77.  
  78.     if (isTextureMovie) {
  79.         // open the movie and store its address in our data structure
  80.         myErr = OpenMovieFile(&myFSSpec, &myMovieFileRef, fsRdPerm);
  81.         if (myErr != noErr)
  82.             goto bail;
  83.  
  84.         myErr = NewMovieFromFile(&(**myTexture).fMovie, myMovieFileRef, NULL, (StringPtr)NULL, newMovieActive, NULL);
  85.         if (myErr != noErr)
  86.             goto bail;
  87.  
  88.         if (myMovieFileRef != 0)
  89.             CloseMovieFile(myMovieFileRef);
  90.             
  91.         SetMovieMatrix((**myTexture).fMovie, NULL);
  92.         MacSetRect(&myBounds, 0, 0, 128, 128);
  93.         SetMovieBox((**myTexture).fMovie, &myBounds);
  94.  
  95.         // get the sound media handler for movies with sound
  96.         if (QTUtils_IsMediaTypeInMovie((**myTexture).fMovie, SoundMediaType) || QTUtils_IsMediaTypeInMovie((**myTexture).fMovie, MusicMediaType))
  97.             (**myTexture).fMediaHandler = QTUtils_GetSoundMediaHandler((**myTexture).fMovie);
  98.         
  99.         // create a new offscreen graphics world (into which we will draw the movie)
  100.         myErr = QTNewGWorld(&myGWorld, kOffscreenPixelType, &myBounds, NULL, NULL, kICMTempThenAppMemory);
  101.         if (myErr != noErr) {
  102.             StopMovie((**myTexture).fMovie);
  103.             DisposeMovie((**myTexture).fMovie);
  104.             (**myTexture).fMovie = NULL;
  105.             goto bail;
  106.         }
  107.     } else {
  108.         // get a graphics importer for the image file
  109.         myErr = GetGraphicsImporterForFile(&myFSSpec, &myImporter);
  110.         if (myErr != noErr)
  111.             goto bail;
  112.         
  113.         // determine the natural size of the image
  114.         myErr = GraphicsImportGetNaturalBounds(myImporter, &myBounds);
  115.         if (myErr != noErr)
  116.             goto bail;
  117.             
  118.         // create a new offscreen graphics world (into which we will draw the image)
  119.         myErr = QTNewGWorld(&myGWorld, kOffscreenPixelType, &myBounds, NULL, NULL, kICMTempThenAppMemory);
  120.         if (myErr != noErr)
  121.             goto bail;
  122.     }
  123.  
  124.     myErr = noErr;
  125.  
  126.     myPixMap = GetGWorldPixMap(myGWorld);
  127.     if (myPixMap != NULL) {
  128.         LockPixels(myPixMap);
  129.         myPictMapAddr = (unsigned long)GetPixBaseAddr(myPixMap);
  130.         
  131.         // get the offset, in bytes, from one row of pixels to the next;
  132.         // according to IM: Imaging With QuickDraw (p. 4-47), the two high-order bits are used as flags,
  133.         // so we need to mask them off (0x3fff == 0b0011 1111 1111 1111)
  134.         myPictRowBytes = (unsigned long)((**myPixMap).rowBytes & 0x3fff);
  135.  
  136.         SetGWorld(myGWorld, NULL);
  137.  
  138.         // create a storage object associated with the new offscreen graphics world
  139.         myStrgPMapPtr = &(**myTexture).fStoragePixmap;
  140.         myStrgPMapPtr->image = Q3MemoryStorage_NewBuffer((void *)myPictMapAddr,
  141.                                                         myPictRowBytes * myBounds.bottom,
  142.                                                         myPictRowBytes * myBounds.bottom);
  143.         myStrgPMapPtr->width        = myBounds.right;
  144.         myStrgPMapPtr->height        = myBounds.bottom;
  145.         myStrgPMapPtr->rowBytes        = myPictRowBytes;
  146.         myStrgPMapPtr->pixelSize    = (**myPixMap).pixelSize;
  147.         myStrgPMapPtr->pixelType    = ((**myPixMap).pixelSize == 16) ? kQ3PixelTypeRGB16 : kQ3PixelTypeRGB32;
  148.         myStrgPMapPtr->bitOrder        = kQ3EndianBig;
  149.         myStrgPMapPtr->byteOrder    = kQ3EndianBig;
  150.     }
  151.     
  152.  
  153.     if (isTextureMovie) {
  154.         TimeBase    myTimeBase;
  155.         
  156.         // start playing the movie in a loop
  157.         SetMovieGWorld((**myTexture).fMovie, myGWorld, GetGWorldDevice(myGWorld));
  158.         GoToBeginningOfMovie((**myTexture).fMovie);
  159.  
  160.         // draw the movie first
  161.         MoviesTask((**myTexture).fMovie, 0);
  162.  
  163.         // throw the movie into loop mode
  164.         myTimeBase = GetMovieTimeBase((**myTexture).fMovie);
  165.         SetTimeBaseFlags(myTimeBase, GetTimeBaseFlags(myTimeBase) | loopTimeBase);
  166.  
  167.         // start playing the movie
  168.         VRMoov_StartMovie((**myTexture).fMovie);        
  169.     } else {
  170.         // draw the picture into the offscreen graphics world
  171.         GraphicsImportSetGWorld(myImporter, myGWorld, NULL);
  172.         GraphicsImportSetBoundsRect(myImporter, &myBounds);
  173.         GraphicsImportDraw(myImporter);
  174.     }
  175.  
  176.     (**myTexture).fpGWorld = myGWorld;
  177.  
  178. bail:
  179.     SetGWorld(myOldGW, myOldGD);
  180.     HUnlock((Handle)myTexture);
  181.  
  182.     if (myImporter != NULL)
  183.         CloseComponent(myImporter);
  184.  
  185.     if (myErr != noErr) {
  186.         if (myTexture != NULL)
  187.             DisposeHandle((Handle)myTexture);
  188.         myTexture = NULL;
  189.     }
  190.         
  191.     return(myTexture);
  192. }
  193.  
  194.  
  195. //////////
  196. //
  197. // VR3DTexture_AddToGroup
  198. // Create a new texture shader based on the pixmap storage data and add it to the group.
  199. //
  200. //////////
  201.  
  202. TQ3Status VR3DTexture_AddToGroup (TextureHdl theTexture, TQ3GroupObject theGroup)
  203. {
  204.     TQ3Status            myStatus = kQ3Failure;
  205.     TQ3StoragePixmap    myStoragePixmap;
  206.     TQ3TextureObject    myTextureObject;
  207.     
  208.     if (theTexture == NULL || theGroup == NULL)
  209.         return(myStatus);
  210.     
  211.     myStoragePixmap = (**theTexture).fStoragePixmap;
  212.     myTextureObject = Q3PixmapTexture_New(&myStoragePixmap);
  213.     if (myTextureObject != NULL) {
  214.  
  215.         TQ3ShaderObject        myTextureShader;
  216.         
  217.         myTextureShader = Q3TextureShader_New(myTextureObject);
  218.         Q3Object_Dispose(myTextureObject);
  219.         
  220.         if (myTextureShader != NULL) {
  221.             TQ3GroupPosition    myPosition = NULL;
  222.             
  223.             // look for an existing texture shader in the group
  224.             Q3Group_GetFirstPositionOfType(theGroup, kQ3SurfaceShaderTypeTexture, &myPosition);
  225.             if (myPosition != NULL) {
  226.             
  227.                 // there is an existing texture shader; just replace it
  228.                 Q3Group_SetPositionObject(theGroup, myPosition, myTextureShader);
  229.             } else {
  230.             
  231.                 // there is no existing texture shader; add one to the group
  232.                 Q3Group_GetFirstPosition(theGroup, &myPosition);
  233.                 Q3Group_AddObjectBefore(theGroup, myPosition, myTextureShader);
  234.             }
  235.             
  236.             Q3Object_Dispose(myTextureShader);
  237.             myStatus = kQ3Success;
  238.         }
  239.     }
  240.  
  241.     return(myStatus);
  242. }
  243.  
  244.  
  245. //////////
  246. //
  247. // VR3DTexture_Delete
  248. // Deallocate the texture.
  249. //
  250. //////////
  251.  
  252. Boolean    VR3DTexture_Delete (TextureHdl theTexture)
  253. {
  254.     PixMapHandle        myPixMap;
  255.  
  256.     if (theTexture == NULL)
  257.         return(false);
  258.  
  259.     HLock((Handle)theTexture);
  260.  
  261.     if ((**theTexture).fMovie != NULL) {
  262.         StopMovie((**theTexture).fMovie);
  263.         DisposeMovie((**theTexture).fMovie);
  264.         (**theTexture).fMovie = NULL;
  265.     }
  266.  
  267.     if ((**theTexture).fpGWorld == NULL) {
  268.         myPixMap = GetGWorldPixMap((**theTexture).fpGWorld);
  269.         if (myPixMap != NULL)
  270.             UnlockPixels(myPixMap);
  271.     
  272.         DisposeGWorld((**theTexture).fpGWorld);
  273.         (**theTexture).fpGWorld = NULL;
  274.     }
  275.  
  276.     if ((**theTexture).fStoragePixmap.image != NULL) {
  277.         Q3Object_Dispose((**theTexture).fStoragePixmap.image);
  278.         (**theTexture).fStoragePixmap.image = NULL;
  279.     }
  280.  
  281.     HUnlock((Handle)theTexture);
  282.     DisposeHandle((Handle)theTexture);
  283.     
  284.     return(true);
  285. }
  286.  
  287.  
  288. //////////
  289. //
  290. // VR3DTexture_NextFrame
  291. // Advance the texture's movie to the next frame.
  292. //
  293. //////////
  294.  
  295. Boolean VR3DTexture_NextFrame (TextureHdl theTexture)
  296. {
  297.     TQ3StoragePixmap    *myStrgPMapPtr;
  298.     long                mySize;
  299.     TQ3Status            myStatus;
  300.     unsigned long        myPictMapAddr;
  301.     PixMapHandle        myPixMap;
  302.  
  303.     // if fpGWorld is non-NULL, then the fMovie is non-NULL and the movie needs updating
  304.     if ((**theTexture).fpGWorld == NULL)
  305.         return(false);
  306.  
  307.     HLock((Handle)theTexture);
  308.  
  309.     if ((**theTexture).fMovie != NULL)
  310.         MoviesTask((**theTexture).fMovie, 0);    // draw the next movie frame
  311.  
  312.     myPixMap = GetGWorldPixMap((**theTexture).fpGWorld);
  313.     myStrgPMapPtr = &(**theTexture).fStoragePixmap;
  314.     mySize = myStrgPMapPtr->height * myStrgPMapPtr->rowBytes;
  315.     myPictMapAddr = (unsigned long)GetPixBaseAddr(myPixMap);
  316.  
  317.     // tell QD3D the buffer changed
  318.     myStatus = Q3MemoryStorage_SetBuffer(myStrgPMapPtr->image, (void *)myPictMapAddr, mySize, mySize);
  319.  
  320.     HUnlock((Handle)theTexture);
  321.     
  322.     return(myStatus == kQ3Success);
  323. }
  324.